//*****************************************************************************
//
//									NVMData.c
//
//*****************************************************************************
//
//
#include "Config.h"
#include "reg.h"
#include "typedefs.h"
#include "printf.h"
#include "CPU.h"
#include "SPI.h"
#include "Global.h"
#include "NVMData.h"

//*****************************************************************************
//
//		NVMPROM App
//
//*****************************************************************************
#include "TouchScreen.h"
void InitNVMData(void)
{
	//----- NVM Data
	NVM_Init();
	if(((NVM_Read(0))==((BYTE)(FWVER>>8)))&&((NVM_Read(1))==((BYTE)FWVER)))
	{
		return;
	}
	NVM_Format();
	NVM_Write(0, (BYTE)(FWVER>>8));
	NVM_Write(1, (BYTE)FWVER);
	
	return;
}

void SaveParaTSC(void)
{
	NVM_Write(2, (U8)((Xres>>8)&0x00FF));
	NVM_Write(3, (U8)(Xres&0x00FF));
	NVM_Write(4, (U8)((Yres>>8)&0x00FF));
	NVM_Write(5, (U8)(Yres&0x00FF));
	NVM_Write(6, (U8)Xslope);
	NVM_Write(7, (U8)Yslope);
	NVM_Write(8, (U8)((((U32)Xoff)>>24)&0x000000FF));
	NVM_Write(9, (U8)((((U32)Xoff)>>16)&0x000000FF));
	NVM_Write(10, (U8)((((U32)Xoff)>>8)&0x000000FF));
	NVM_Write(11, (U8)(((U32)Xoff)&0x000000FF));
	NVM_Write(12, (U8)((((U32)Yoff)>>24)&0x000000FF));
	NVM_Write(13, (U8)((((U32)Yoff)>>16)&0x000000FF));
	NVM_Write(14, (U8)((((U32)Yoff)>>8)&0x000000FF));
	NVM_Write(15, (U8)(((U32)Yoff)&0x000000FF));
	//Printf("\r\n SLOF SVE 0x%x 0x%x 0x%bx 0x%bx 0x%lx 0x%lx", Xres, Yres, Xslope, Yslope, Xoff, Yoff);
	//Printf("\r\n SLOF SVE %d %d %bd %bd %ld %ld", Xres, Yres, Xslope, Yslope, Xoff, Yoff);

	return;
}

void LoadParaTSC(void)
{
	Xres = (U16)(NVM_Read(2))<<8;
	Xres = Xres|((U16)(NVM_Read(3)));
	Yres = (U16)(NVM_Read(4))<<8;
	Yres = Yres|((U16)(NVM_Read(5)));
	//Printf("\r\n LoadParaTSC 0x%x 0x%x", Xres, Yres);
	if ((Xres!=DEF_XRES) || (Yres!=DEF_YRES))
	{
		Xslope = DEF_XSLOPE;
		Yslope = DEF_YSLOPE;
		Xoff   = DEF_XOFF;
		Yoff   = DEF_YOFF;
		Xres   = DEF_XRES;
		Yres   = DEF_YRES;

		return;
	}
	
	Xslope = (S8)NVM_Read(6);
	Yslope = (S8)NVM_Read(7);
	Xoff = (LONG)((U32)(NVM_Read(8))<<24);
	Xoff = (LONG)(((U32)Xoff)|((U32)(NVM_Read(9))<<16));
	Xoff = (LONG)(((U32)Xoff)|((U32)(NVM_Read(10))<<8));
	Xoff = (LONG)(((U32)Xoff)|((U32)(NVM_Read(11))));
	Yoff = (LONG)((U32)(NVM_Read(12))<<24);
	Yoff = (LONG)(((U32)Yoff)|((U32)(NVM_Read(13))<<16));
	Yoff = (LONG)(((U32)Yoff)|((U32)(NVM_Read(14))<<8));
	Yoff = (LONG)(((U32)Yoff)|((U32)(NVM_Read(15))));
	//Printf("\r\n SLOF LOD 0x%x 0x%x 0x%bx 0x%bx 0x%lx 0x%lx", Xres, Yres, Xslope, Yslope, Xoff, Yoff);
	//Printf("\r\n SLOF LOD %d %d %bd %bd %ld %ld", Xres, Yres, Xslope, Yslope, Xoff, Yoff);

	return;
}


//*****************************************************************************
//
//		NVMPROM Emulation
//
//*****************************************************************************
//		Format: For each 4 bytes [Index] [Index^FF] [Data] [Data^FF]
//
//
#define SPI_SECTOR_SIZE		0x1000

#define NVM_SPI_SECTOR0		0x0F0000L
#define NVM_SPI_SECTOR1		0x0F1000L

#define NVM_MAX_INDEX		16
#define NVM_BUF_SIZE		(NVM_MAX_INDEX*4)


XDATA BYTE NVMBuffer[NVM_BUF_SIZE] _at_ 0;			// SPI DMA has limitation under 1K address, 0x400
DWORD NVM_ValidSector = NVM_SPI_SECTOR0;
WORD  NVM_WritePos = 0;
//=============================================================================
//
//=============================================================================
void NVM_Format(void)
{
	BYTE 	j;

	SPI_SetAccess();

	//SPI_SetModeByRegister();					// Match DMA mode with SPI-read

	SPI_SectorErase( NVM_SPI_SECTOR0 );
	SPI_SectorErase( NVM_SPI_SECTOR1 );

	NVM_ValidSector = NVM_SPI_SECTOR0;

	NVM_WritePos = 0;		
		
	for(j=0; j<NVM_MAX_INDEX; j++) {
		NVMBuffer[0] = j;
		NVMBuffer[1] = 0xff^j;
		NVMBuffer[2] = 0xff;
		NVMBuffer[3] = 0x00;

		SPI_PageProgram( NVM_ValidSector + NVM_WritePos, NVMBuffer, 4 );

		NVM_WritePos+=4;
	}

	SPI_RevertAccess();
}
//=============================================================================
//
//=============================================================================
void NVM_Init(void)
{
	BYTE i=0, j;

	SPI_SetAccess();
	//----- Check NVMPROM corruption -------------------------


	//----- Find NVM_ValidSector and NVM_WritePos -------------

	SPI_ReadData2xdata( NVM_SPI_SECTOR0, NVMBuffer, 4L );
	//Printf("\r\ntest2");
	for(i=1; i<4; i++){
		NVMBuffer[0] &= NVMBuffer[i];
	}
	NVM_ValidSector = (NVMBuffer[0]==0xff)?(NVM_SPI_SECTOR1):(NVM_SPI_SECTOR0);

	//Printf("\n    NVM_ValidSector = %06lx ", NVM_ValidSector );

	for(j=0; j<SPI_SECTOR_SIZE/NVM_BUF_SIZE; j++) {

		SPI_ReadData2xdata( NVM_ValidSector + j * NVM_BUF_SIZE, NVMBuffer, NVM_BUF_SIZE );

		for(i=0; i<NVM_BUF_SIZE; i+=4) {
			if( NVMBuffer[i]==0xff && NVMBuffer[i+1]==0xff ) {
				NVM_WritePos = j*NVM_BUF_SIZE + i;
				//Printf("\n    NVM_WritePos    = %04x ", NVM_WritePos );
				SPI_RevertAccess();
				return;
			}
		}
	}

	NVM_WritePos = SPI_SECTOR_SIZE;
	//Printf("\nNVM_WritePos = %02bx ", NVM_WritePos );

	SPI_RevertAccess();
}
//=============================================================================
//
//=============================================================================
BYTE NVM_Read(BYTE index)
{
	BYTE i, j, val, valid=0;

	SPI_SetAccess();
	for(j=0; j<SPI_SECTOR_SIZE/NVM_BUF_SIZE; j++) {

		SPI_ReadData2xdata( (NVM_ValidSector+(j*NVM_BUF_SIZE)), NVMBuffer, NVM_BUF_SIZE );

		for(i=0; i<NVM_BUF_SIZE; i+=4) {
			if( NVMBuffer[i]==0xff && NVMBuffer[i+1]==0xff ) break;

			if( NVMBuffer[i]==index ) {
				if( ((NVMBuffer[i]+NVMBuffer[i+1])==0xff) && ((NVMBuffer[i+2]+NVMBuffer[i+3])==0xff) ) {
					valid = 1;
					val = NVMBuffer[i+2];
					//Printf("\nNVM_ReadPos = %bd _at_ %08lx", index, (NVM_ValidSector+(j*NVM_BUF_SIZE))+i );
				}else {
					//Printf("\nNVMPROM is corrupted !!! addr=%06lx [%02bx %02bx %02bx %02bx]\n", (NVM_ValidSector+(j*NVM_BUF_SIZE)), NVMBuffer[i], NVMBuffer[i+1], NVMBuffer[i+2], NVMBuffer[i+3]);
				}
			}
		}
		if( NVMBuffer[i]==0xff && NVMBuffer[i+1]==0xff ) break;
	}
	SPI_RevertAccess();

	if( valid ) return val;

	//Printf("\nCannot find NVMPROM data in index %02bx ", index);
	return 0;
}
//=============================================================================
//
//=============================================================================
void NVM_ReadAll(BYTE *buf)
{
	BYTE i, j;

	SPI_SetAccess();

	for(j=0; j<SPI_SECTOR_SIZE/NVM_BUF_SIZE; j++) {

		SPI_ReadData2xdata( (NVM_ValidSector+(j*NVM_BUF_SIZE)), NVMBuffer, NVM_BUF_SIZE );

		for(i=0; i<NVM_BUF_SIZE; i+=4) {
			if( NVMBuffer[i]==0xff && NVMBuffer[i+1]==0xff ) break;

			if( ((NVMBuffer[i]^NVMBuffer[i+1])==0xff) && ((NVMBuffer[i+2]^NVMBuffer[i+3])==0xff) ){
				buf[NVMBuffer[i]] = NVMBuffer[i+2];
			}else{
				//Printf("\nNVMPROM is corrupted !!! addr=%06lx [%02bx %02bx %02bx %02bx]", NVMBuffer[i], NVMBuffer[i+1], NVMBuffer[i+2], NVMBuffer[i+3]);
			}
		}
	}
	SPI_RevertAccess();
}
//=============================================================================
//
//=============================================================================
void NVM_Write(BYTE index, BYTE dat)
{
	BYTE j;
	BYTE buf[NVM_MAX_INDEX];

	SPI_SetAccess();

	//----- If SPI sector is full, reconstruct 
	if( NVM_WritePos>=SPI_SECTOR_SIZE ) {

		//Printf("\nSPI sector full Full and Erase...");
		SPI_RevertAccess();

		NVM_ReadAll( buf );

		SPI_SetAccess();

		SPI_SectorErase( NVM_ValidSector );
		NVM_ValidSector = ( NVM_ValidSector==NVM_SPI_SECTOR0 )?(NVM_SPI_SECTOR1):(NVM_SPI_SECTOR0);

		NVM_WritePos = 0;		
		for(j=0; j<NVM_MAX_INDEX; j++) {
			NVMBuffer[NVM_WritePos] = j;
			NVMBuffer[NVM_WritePos+1] = 0xff^j;
			NVMBuffer[NVM_WritePos+2] = buf[j];
			NVMBuffer[NVM_WritePos+3] = 0xff^buf[j];

			NVM_WritePos+=4;
		}
		SPI_PageProgram( NVM_ValidSector, NVMBuffer, NVM_WritePos );
	}

	//----- Write data
	NVMBuffer[0] = index;
	NVMBuffer[1] = 0xff^index;
	NVMBuffer[2] = dat;
	NVMBuffer[3] = 0xff^dat;

	SPI_PageProgram( (NVM_ValidSector+NVM_WritePos), NVMBuffer, 4 );

	NVM_WritePos += 4;
	//Printf("\nNVM_WritePos = %04x _at_ %08lx", NVM_WritePos, (NVM_ValidSector+NVM_WritePos) );

	SPI_RevertAccess();
}



